/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.freedoit.gui;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JOptionPane;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.freedoit.FreeDoit;
import org.freedoit.FreeDoitConfig;
import org.freedoit.common.data.FreeDoitAuthResponse;
import org.freedoit.common.util.FreeDoitDataUtils;
import org.freedoit.dao.DAOFactory;
import org.freedoit.om.SyncKey;
import org.freedoit.util.EncryptEngine;
import org.freedoit.util.Utils;

/**
 *
 * @author wanglei
 */
public class LoginDialog extends javax.swing.JDialog {

    /**
     * Creates new form LoginDialog
     */
    public LoginDialog(java.awt.Frame parent, boolean modal) {
        this(parent, modal, "");
    }
    public LoginDialog(java.awt.Frame parent, boolean modal, String userName) {
        super(parent, modal);
        if (userName == null) {
            this.userName = "";
        } else {
            this.userName = userName;
        }
        initComponents();
        Utils.displayAtCentralScreen(this);
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jLabelUserName = new javax.swing.JLabel();
        jTextFieldUserName = new javax.swing.JTextField();
        jLabelPassword = new javax.swing.JLabel();
        jPasswordFieldPassword = new javax.swing.JPasswordField();
        jLabelForgetPassword = new javax.swing.JLabel();
        jCheckBoxRememberMe = new javax.swing.JCheckBox();
        jButtonLogin = new javax.swing.JButton();
        jLabelNewAccount = new javax.swing.JLabel();

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        setTitle("Doit.Free");
        setModal(true);
        setResizable(false);

        jLabelUserName.setFont(FreeDoitConfig.getFont(0, 14));
        jLabelUserName.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
        jLabelUserName.setText(FreeDoitConfig.getText("dialog.login.label.username"));

        jTextFieldUserName.setFont(FreeDoitConfig.getFont(0, 14));
        jTextFieldUserName.setText(userName);

        jLabelPassword.setFont(FreeDoitConfig.getFont(0, 14));
        jLabelPassword.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
        jLabelPassword.setText(FreeDoitConfig.getText("dialog.login.label.password"));

        jPasswordFieldPassword.setFont(FreeDoitConfig.getFont(0, 14));

        jLabelForgetPassword.setFont(FreeDoitConfig.getFont(0, 11));
        jLabelForgetPassword.setForeground(new java.awt.Color(102, 102, 102));
        jLabelForgetPassword.setText(FreeDoitConfig.getText("dialog.login.label.forget.password"));
        jLabelForgetPassword.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
        jLabelForgetPassword.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                jLabelForgetPasswordMouseClicked(evt);
            }
        });

        jCheckBoxRememberMe.setFont(FreeDoitConfig.getFont(0, 11));
        jCheckBoxRememberMe.setText(FreeDoitConfig.getText("dialog.login.checkbox.remember.me"));

        jButtonLogin.setFont(FreeDoitConfig.getFont(0, 14));
        jButtonLogin.setText(FreeDoitConfig.getText("dialog.login.button.login"));
        jButtonLogin.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                jButtonLoginMouseClicked(evt);
            }
        });

        jLabelNewAccount.setFont(FreeDoitConfig.getFont(0, 14));
        jLabelNewAccount.setForeground(new java.awt.Color(0, 204, 204));
        jLabelNewAccount.setText(FreeDoitConfig.getText("dialog.login.label.new.account"));
        jLabelNewAccount.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
        jLabelNewAccount.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                jLabelNewAccountMouseClicked(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGap(40, 40, 40)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                    .addComponent(jLabelPassword, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(jLabelUserName))
                .addGap(18, 18, 18)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jCheckBoxRememberMe)
                    .addComponent(jLabelForgetPassword)
                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                        .addComponent(jTextFieldUserName)
                        .addComponent(jPasswordFieldPassword, javax.swing.GroupLayout.PREFERRED_SIZE, 238, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addComponent(jButtonLogin, javax.swing.GroupLayout.PREFERRED_SIZE, 82, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addContainerGap(102, Short.MAX_VALUE))
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addComponent(jLabelNewAccount)
                .addGap(43, 43, 43))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGap(38, 38, 38)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabelUserName)
                    .addComponent(jTextFieldUserName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addGap(18, 18, 18)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabelPassword)
                    .addComponent(jPasswordFieldPassword, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(jLabelForgetPassword)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(jCheckBoxRememberMe)
                .addGap(18, 18, 18)
                .addComponent(jButtonLogin)
                .addGap(18, 18, 18)
                .addComponent(jLabelNewAccount, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(36, Short.MAX_VALUE))
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    public String getUserName() {
        return this.userName;
    }
    
    public String getPassword() {
        return this.password;
    }
    
    public boolean isRememberMe() {
        return this.blnRememberMe;
    }
    
    public boolean isLogin() {
        return this.blnIsLogin;
    }
    private boolean checkBeforeLogin() {
        String requiredStr = this.jTextFieldUserName.getText();
        if (requiredStr == null || "".equals(requiredStr)) {
            JOptionPane.showMessageDialog(this, "User name is required", "Error", JOptionPane.ERROR_MESSAGE);
            this.jTextFieldUserName.setFocusable(true);
            return false;
        }
        
        requiredStr = new String(this.jPasswordFieldPassword. getPassword());
        if (requiredStr == null || "".equals(requiredStr)) {
            JOptionPane.showMessageDialog(this, "Password is required", "Error", JOptionPane.ERROR_MESSAGE);
            this.jTextFieldUserName.setFocusable(true);
            return false;
        }

        return true;
    }
    
    public static boolean doLogin(String username, String key, StringBuffer sbErrorMessage) {
        HttpPost httppost = new HttpPost(FreeDoitConfig.AUTH_SERVICE);

        List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(1);
        nameValuePairs.add(new BasicNameValuePair("user", username));
        String keyRandom = FreeDoitDataUtils.oneWayEncryptPassword(key);
        nameValuePairs.add(new BasicNameValuePair("key", keyRandom));
        
        Long clientId = null;
        // If contain this user's database
        if (DAOFactory.userNameExist(username)) {            
            // switch user
            DAOFactory.switchUser(username);
            // retrieve client id
            clientId = DAOFactory.getSyncKeyDAO().getClientId();
        }

        if (clientId == null) {
            clientId = SyncKey.NO_CLIENT_ID;
        }
        nameValuePairs.add(new BasicNameValuePair("clientId", clientId.toString()));

        String responseBody = null;
        ResponseHandler<String> responseHandler = new BasicResponseHandler();
        UrlEncodedFormEntity e = null;
        try {
            e = new UrlEncodedFormEntity(nameValuePairs);
            httppost.setEntity(e);
            responseBody = FreeDoit.getHttpClient().execute(httppost, responseHandler);
        } catch (ClientProtocolException ex) {
            Logger.getLogger(DoitFrame.class.getName()).log(Level.SEVERE, null, ex);
            sbErrorMessage.append(ex.getMessage());
            return false;
        } catch (IOException ex) {
            Logger.getLogger(DoitFrame.class.getName()).log(Level.SEVERE, null, ex);
            sbErrorMessage.append(ex.getMessage());
            return false;
        } finally {
            if (e != null) {
                try {
                    EntityUtils.consume(e);
                } catch (IOException ex) {
                    Logger.getLogger(DoitFrame.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
        
//        if (responseBody != null) { //decrypt
//            responseBody = FreeDoitDataUtils.decryptByAES(responseBody, key);
//        }

        // parse response
        if (responseBody == null) {
            sbErrorMessage.append("fail to get response from server");
            return false;
        } else {
            System.out.println(responseBody);
            
            FreeDoitAuthResponse result = FreeDoitDataUtils.createStandardJson().fromJson(responseBody, 
                    new com.google.gson.reflect.TypeToken<FreeDoitAuthResponse>() {  
                        }.getType());
            if (result.getCode() == FreeDoitAuthResponse.CODE_OK) {
                // If login OK, switch user
                DAOFactory.switchUser(username);
                if (clientId.longValue() != result.getClientId()) {
                    DAOFactory.getSyncKeyDAO().setClientId(result.getClientId());
                }
                
                // Update Encrypt Engine
                EncryptEngine.reset(result.getKeyModulus(), result.getKeyExponent(), key);
                
                // If login OK, update user name
                return true;
            } else {
                sbErrorMessage.append("Error code:").append(result.getCode());
                return false;
            }
        }
        
    }
    private boolean doLogin(StringBuffer sbErrorMessage) {
        String password = FreeDoitDataUtils.hashString(
                new String(this.jPasswordFieldPassword. getPassword()));
        return LoginDialog.doLogin(this.jTextFieldUserName.getText(), 
                password, sbErrorMessage);
    }
    private void doAfterLogin() {
        this.userName = this.jTextFieldUserName.getText();
        this.password = new String(this.jPasswordFieldPassword. getPassword());
        this.blnRememberMe = this.jCheckBoxRememberMe.isSelected();
        this.blnIsLogin = true;
        this.dispose();
        this.setVisible(false);
    }
    private void jLabelForgetPasswordMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jLabelForgetPasswordMouseClicked
        // TODO add your handling code here:
    }//GEN-LAST:event_jLabelForgetPasswordMouseClicked

    private void jLabelNewAccountMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jLabelNewAccountMouseClicked
        // TODO add your handling code here:
    }//GEN-LAST:event_jLabelNewAccountMouseClicked

    private void jButtonLoginMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jButtonLoginMouseClicked
        // TODO add your handling code here:
        if (checkBeforeLogin()) {
            StringBuffer sbErrorMessage = new StringBuffer();
            if (doLogin(sbErrorMessage)) {
                doAfterLogin();
            } else {
                JOptionPane.showMessageDialog(this, sbErrorMessage.toString(), "Login Error", JOptionPane.ERROR_MESSAGE);
            }
        }
    }//GEN-LAST:event_jButtonLoginMouseClicked

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /* Set the Nimbus look and feel */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(LoginDialog.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(LoginDialog.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(LoginDialog.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(LoginDialog.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /* Create and display the dialog */
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                LoginDialog dialog = new LoginDialog(new javax.swing.JFrame(), true);
                dialog.addWindowListener(new java.awt.event.WindowAdapter() {
                    @Override
                    public void windowClosing(java.awt.event.WindowEvent e) {
                        System.exit(0);
                    }
                });
                dialog.setVisible(true);
            }
        });
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton jButtonLogin;
    private javax.swing.JCheckBox jCheckBoxRememberMe;
    private javax.swing.JLabel jLabelForgetPassword;
    private javax.swing.JLabel jLabelNewAccount;
    private javax.swing.JLabel jLabelPassword;
    private javax.swing.JLabel jLabelUserName;
    private javax.swing.JPasswordField jPasswordFieldPassword;
    private javax.swing.JTextField jTextFieldUserName;
    // End of variables declaration//GEN-END:variables
    private String userName;
    private String password;
    private boolean blnRememberMe;
    private boolean blnIsLogin;
}
